血色先锋队

题目 血色先锋队

巫妖王的天灾军团终于卷土重来,血色十字军组织了一支先锋军前往诺森德大陆对抗天灾军团,以及一切沾有亡灵气息的生物。孤立于联盟和部落的血色先锋军很快就遭到了天灾军团的重重包围,现在他们将主力只好聚集了起来,以抵抗天灾军团的围剿。可怕的是,他们之中有人感染上了亡灵瘟疫,如果不设法阻止瘟疫的扩散,很快就会遭到灭顶之灾。大领主阿比迪斯已经开始调查瘟疫的源头。原来是血色先锋军的内部出现了叛徒,这个叛徒已经投靠了天灾军团,想要将整个血色先锋军全部转化为天灾军团!无需惊讶,你就是那个叛徒。在你的行踪败露之前,要尽快完成巫妖王交给你的任务。

题目描述

军团是一个n 行 m列的矩阵,每个单元是一个血色先锋军的成员。感染瘟疫的人,每过一个小时,就会向四周扩散瘟疫,直到所有人全部感染上瘟疫。你已经掌握了感染源的位置,任务是算出血色先锋军的领主们感染瘟疫的时间,并且将它报告给巫妖王,以便对血色先锋军进行一轮有针对性的围剿。

输入格式

第 1 行:四个整数 n,m,a,b,表示军团矩阵有 n 行 m 列。有 a 个感染源,b 为血色敢死队中领主的数量。

接下来 a 行:每行有两个整数 x,y,表示感染源在第 x 行第 y 列。

接下来 b 行:每行有两个整数 x,y,表示领主的位置在第 x 行第 y 列。

输出格式

第 1 至 b 行:每行一个整数,表示这个领主感染瘟疫的时间,输出顺序与输入顺序一致。如果某个人的位置在感染源,那么他感染瘟疫的时间为 0。

样例 #1

样例输入 #1

5 4 2 3
1 1
5 4
3 3
5 3
2 4

样例输出 #1

3
1
3

提示

输入输出样例 1 解释

如下图,标记出了所有人感染瘟疫的时间以及感染源和领主的位置。

3j3g02cn-c0cf1701

数据规模与约定

对于 \(100\%\) 的数据,保证 \(1\le n,m\le500\),\(1\le a,b\le10^5\)。

思路分析

image-c1afda79

把所有起点都先入队列 就会呈现这种多源并行拓展的趋势

因为访问过的点不会再访问 所以只会保留第一次被找到时所花的距离

要看哪个点直接做查询即可

代码实现

#include<bits/stdc++.h>

using namespace std;

#define endl '\n'

typedef pair<int,int> PII;

const int N=510;

int d[N][N];

int n,m;

int dx[4]={-1,0,1,0};

int dy[4]={0,1,0,-1};

bool isVaild(int x,int y){

	return x>=1 && x<=n && y>=1 && y<=m && d[x][y]==-1;

}

queue<PII> q;

void bfs(){

	while(!q.empty()){

		auto cur=q.front();q.pop();

		int ux=cur.first,uy=cur.second;

		for(int i=0;i<4;i++){

			int nx=ux+dx[i],ny=uy+dy[i];

			if(isVaild(nx,ny)){

				d[nx][ny]=d[ux][uy]+1;

				q.push({nx,ny});

			}

		}

	}

}

int main()

{

	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);

	cin>>n>>m;

	int a,b;cin>>a>>b;

	memset(d,-1,sizeof d);

	while(a--){

		int tx,ty;cin>>tx>>ty;

		q.push({tx,ty});

		d[tx][ty]=0;

	}

	bfs();

	while(b--){

		int tx,ty;cin>>tx>>ty;

		cout<<d[tx][ty]<<endl;

	}

	return 0;

}

同类题型

视频讲解


⬅️ 矩阵距离 🏠 00-刷题理模型 ➡️ 最小步数